/*
 * @Author: AiLjx
 * @Date: 2022-05-14 22:37:06
 * @LastEditors: AiLjx
 * @LastEditTime: 2022-07-01 22:43:02
 */
//请注意运行V6版本案例时务必重新安装一下V6路由
//安装路由：npm i react-router-dom@6

// V6版本react-router特性变更：
// 1. path：与当前页面对应的URL匹配。
// 2. element：新增，用于决定路由匹配时，渲染哪个组件。代替，v5的component和render。
// 3. 代替了
// 4. <Outlet></Outlet>让嵌套路由更简单
// 5. useNavigate代替useHistory
// 6. 移除了的activeClassName 和 activeStyle
// 7. 钩子useRoutes代替react-router-config
// 8. https://reactrouter.com/docs/en/v6/upgrading/v5

import { useEffect } from "react";
import {
    BrowserRouter,
    Link,
    NavLink,
    Routes,
    Route,
    Navigate,
    useNavigate,
} from "react-router-dom";

import "./App.css";

//引进路由页面组件
import About from "./views/About";
import Home from "./views/Home";
import Login from "./views/Login";
import Center from "./views/Center";

//路由配置
function App() {
    return (
        // 声明当前要用一个非hash模式的路由
        // HashRouter：hash模式的路由（路径带#）
        // BrowserRouter：非hash模式的路由
        <BrowserRouter>
            {/* 声明式导航 */}
            {/* 指定跳转的组件，to用来配置路由地址,Link和NavLink组件可以用在其它组件中
            (前提是必须在Router（BrowserRouter或HashRouter）内部，一般情况下Router都
            在根组件（App）最外层，所有Link和NavLink组件几乎可以放在任何地方)，
            这里是为了方便直接在这里用了，使用这种方式跳转称为声明式导航*/}
            <Link to='/'>首页 </Link>
            <Link to='/center'>个人中心 </Link>

            {/* NavLink具备Link的所有功能，并添加了高亮显示
            在NavLink被激活选中时会被自动添加一个class：active */}
            <NavLink to='/about'>关于 </NavLink>
            {/* 自定义NavLink选中时的class */}
            {/*NavLink具有一个className属性，它接收一个回调函数，
            回调函数可获得的参数中有一个isActive可以判断是否选中，
            这里是点击登录时，给登录加上自定义的AiljxActive class，
            使登录变成黄色  */}
            <NavLink
                to='/login'
                className={({ isActive }) => (isActive ? "AiljxActive" : "")}>
                登录
            </NavLink>

            {/* 路由出口，路由对应的组件会在这里进行渲染 */}
            <Routes>
                {/* 指定路径和组件的对应关系 */}
                <Route path='/home' element={<Home />}></Route>

                <Route path='/login' element={<Login />}></Route>

                {/* 想让页面能同时接收这两种形式的传参，可以写两个路由 */}
                {/* 使用Params */}
                {/* id是占位符，取参的时候取id */}
                <Route path='/about/:id' element={<About />}></Route>
                {/* 使用SearchParams */}
                <Route path='/about' element={<About />}></Route>

                {/* 路由鉴权 */}
                {/* 封装AuthComponent组件进行路由鉴权 */}
                <Route
                    path='/center'
                    element={
                        <AuthComponent>
                            {/* 鉴权路由组件中添加需要鉴权的组件 */}
                            <Center></Center>
                        </AuthComponent>
                    }></Route>

                {/* 路由重定向，V6版本删除了Redirect组件
                推荐方案一：可使用Navigate组件替代 */}
                <Route path='/' element={<Navigate to='/home' />}></Route>
                {/* 推荐方案二：利用useNavigate自定义Redirect组件 */}
                <Route path='*' element={<Redirect to='/home' />}></Route>
            </Routes>
        </BrowserRouter>
    );
}

export default App;

// 利用useNavigate hooks 自定义重定向组件
function Redirect({ to }) {
    const nav = useNavigate();
    useEffect(() => {
        // 编程式导航，在JS逻辑中进行页面跳转
        // 第一个参数跳转地址，第二个参数是配置项
        // replace: true开启重定向
        nav(to, { replace: true });
    });
}

// 路由鉴权组件
function AuthComponent({ children }) {
    // localStorage中存在V6Router时才渲染组件，不然就重定向到登录页
    return localStorage.getItem("V6Router") ? (
        children
    ) : (
        <Navigate to='/login' />
    );
}

// react-router简介
// react-router ：核心模块，包含 React 路由大部分的核心功能，包括路由匹配算法和大部分核心组
// 件和钩子。
// react-router-dom：React应用中用于路由的软件包，包括react-router的所有内容，并添加了一
// 些特定于 DOM 的 API，包括但不限于BrowserRouter、HashRouter和Link。
// react-router-native： 用于开发React Native应用，包括react-router的所有内容，并添加了一些
// 特定于 React Native 的 API，包括但不限于NativeRouter和Link。
